package com.demo.topics;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.demo.topics.data.Topic;
import com.demo.topics.data.VideoInfo;
import com.demo.topics.util.ImageFetcher;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.SearchListResponse;
import com.google.api.services.youtube.model.SearchResult;

public class SearchResultsActivity extends ListActivity {
    private final static String TAG = SearchResultsActivity.class
            .getSimpleName();

    private String mDisplayName;
    private String mDescription;
    private String mMid;

    private String mApiKey;

    VideoSearchResultAdapter mListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle bundle = getIntent().getExtras();
        mDisplayName = bundle.getString(Topic.DISPLAY_NAME);
        mDescription = bundle.getString(Topic.DESCRIPTION);
        mMid = bundle.getString(Topic.MID);

        // Let's read the API key from keys.xml. Populate this if you haven't
        // done so already
        mApiKey = getResources().getString(R.string.api_key);

        setTitle(getResources().getString(R.string.search_results) + ": "
                + mDisplayName);
        setContentView(R.layout.activity_search_results);

        // Show the Up button in the action bar.
        setupActionBar();

        // Let's set the adapter
        mListAdapter = new VideoSearchResultAdapter(this,
                R.layout.video_search_result_list);
        getListView().setAdapter(mListAdapter);

        // Create an instance of AsyncTask to make the API call and run it
        new CallYouTubeAPITask(mListAdapter).execute(mMid);
    }

    /**
     * Set up the {@link android.app.ActionBar}.
     */
    private void setupActionBar() {
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Handle the click on a Video Item using YouTube's Android SDK.
     *
     * @see https://developers.google.com/youtube/android/player/
     */
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        VideoInfo info = mListAdapter.getItem(position);
        Log.d(TAG, "Selected item: " + info.getTitle());

        Intent playVideoIntent = new Intent(this, VideoPlayerActivity.class);
        playVideoIntent.putExtra(VideoPlayerActivity.VIDEO_ID, info.getId());
        playVideoIntent.putExtra(VideoPlayerActivity.VIDEO_TITLE, info.getTitle());
        playVideoIntent.putExtra(VideoPlayerActivity.VIDEO_DESCRIPTION, info.getDescription());
        playVideoIntent.putExtra(VideoPlayerActivity.TOPIC_NAME, mDisplayName);
        startActivity(playVideoIntent);
    }

    /**
     * Background task to make calls to the YouTube API and update the ListView.
     * The parameter passed to the asynctask is a list of mids corresponding to
     * search topics. These mids are fetched in the main activity from the
     * Topics API.
     *
     * @author Ikai Lan <ikai@google.com>
     */
    private class CallYouTubeAPITask extends
            AsyncTask<String, Void, List<VideoInfo>> {

        // We need a reference to this so we can update the adapter with new
        // data as it arrives
        private VideoSearchResultAdapter mListAdapter;

        public CallYouTubeAPITask(VideoSearchResultAdapter listAdapter) {
            mListAdapter = listAdapter;
        }

        /**
         * Instantiates the YouTube client and makes API calls. When this is
         * done, returns the number of results returned.
         */
        @Override
        protected List<VideoInfo> doInBackground(String... mids) {
            List<VideoInfo> videos = new ArrayList<VideoInfo>();

            // TODO: Instantiate the YouTube client
            String apiKey = getResources().getString(R.string.api_key);

            HttpTransport httpTransport = new NetHttpTransport();
            JsonFactory jsonFactory = new JacksonFactory();

            YouTube yt = new YouTube.Builder(httpTransport, jsonFactory, new HttpRequestInitializer() {
                @Override
                public void initialize(HttpRequest httpRequest) throws IOException {
                }
            }).setApplicationName("YouTubeMobileCodeLab/0.1")
                    .build();

            try {
                SearchListResponse response = yt.search().list("id,snippet")
                        .setKey(apiKey)
                        .setTopicId(mids[0])
                        .setType("video")
                        .setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)")
                        .setMaxResults(25l)
                        .execute();

                List<SearchResult> results = response.getItems();
                for(SearchResult result : results) {
                    VideoInfo info = new VideoInfo();
                    info.setId(result.getId().getVideoId());
                    info.setTitle(result.getSnippet().getTitle());
                    info.setDescription(result.getSnippet().getDescription());
                    // TODO make sure this one doesn't crash
                    info.setThumbnailUrl(result.getSnippet().getThumbnails().get("default").getUrl());
                    Log.d(TAG, "Got search result: " + info);
                    videos.add(info);
                }
            } catch (IOException e) {
                Log.e(TAG, "Got IOException: " + e);
            }
            return videos;
        }

        /**
         * Iterate through the videos received and update the adapter with the
         * new data.
         *
         * @param result a list of {@link VideoInfo} objects that match the
         *               corresponding mids
         */
        @Override
        protected void onPostExecute(List<VideoInfo> result) {
            mListAdapter.clear();
            mListAdapter.addAll(result);
            // TODO: handle "no results" better
        }
    }

    /**
     * Adapter for handling video search results for our ListView
     *
     * @author Ikai Lan <ikai@google.com>
     */
    private static class VideoSearchResultAdapter extends
            ArrayAdapter<VideoInfo> {
        private Activity mContext;
        private int mLayoutResourceId;

        // This is a custom class I wrote that handles the problem of loading
        // images in the background,
        // caching them, and rendering to an ImageView when necessary.
        private ImageFetcher mFetcher;

        public VideoSearchResultAdapter(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
            mContext = (Activity) context;
            mLayoutResourceId = textViewResourceId;

            mFetcher = new ImageFetcher(mContext);
        }

        /**
         * Overriding the default getView so we can render our custom layout.
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater inflater = mContext.getLayoutInflater();
                v = inflater.inflate(mLayoutResourceId, null);
            }

            // Make sure we are in bounds and draw the item
            if (position < getCount()) {
                TextView title = (TextView) v.findViewById(R.id.video_title);
                TextView description = (TextView) v
                        .findViewById(R.id.video_description);

                VideoInfo info = getItem(position);

                // Set the values here
                title.setText(info.getTitle());
                description.setText(info.getDescription());

                // Add an image fetch job to the queue
                final ImageView thumbnail = (ImageView) v
                        .findViewById(R.id.video_thumbnail);

                ImageFetcher.ImageFetchJob job = new ImageFetcher.ImageFetchJob(
                        info.getThumbnailUrl());
                job.setOnFetchCompleteListener(new ImageFetcher.OnFetchCompleteListener() {

                    @Override
                    public void onFetchComplete(Bitmap result) {
                        thumbnail.setImageBitmap(result);
                    }
                });
                mFetcher.enqueue(job);

            }
            return v;
        }
    }
}
